package com.hjh.testdemo.ui.usb.accessory

import android.annotation.SuppressLint
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.hardware.usb.UsbAccessory
import android.hardware.usb.UsbManager
import android.view.View
import androidx.core.content.ContextCompat
import androidx.lifecycle.lifecycleScope
import com.elvishew.xlog.XLog
import com.hjh.core.activity.BaseFragment
import com.hjh.testdemo.databinding.FragmentUsbAccessoryBinding
import com.hjh.usb.accessory.communication.UsbAccessoryCommunicator
import com.hjq.toast.Toaster
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

/**
 * @author： hjh
 * @createDate： 2025/6/16 19:06
 * @description：
 * @qq： 3472903821
 * @version: 1.0
 */
class UsbAccessoryFragment : BaseFragment<FragmentUsbAccessoryBinding>() {

    companion object {
        private const val ACTION_USB_PERMISSION = "com.hjh.USB_ACCESSORY_PERMISSION"
    }

    private lateinit var usbManager: UsbManager
    private var communicator: UsbAccessoryCommunicator? = null

    override fun initView() {
        usbManager = requireContext().getSystemService(Context.USB_SERVICE) as UsbManager

        registerReceiver()

        checkAndRequestAccessory()
    }

    override fun initListener() {
        binding.sendButton.setOnClickListener {
            val inputString = binding.inputEdittext.text.toString()
            if (inputString.isNotEmpty()) {
                sendString(inputString)
                binding.inputEdittext.setText("")
            }
        }
        binding.refreshButton.setOnClickListener {
            checkAndRequestAccessory()
        }
    }

    override fun onDestroyView() {
        requireActivity().unregisterReceiver(usbReceiver)
        super.onDestroyView()
    }

    private fun registerReceiver() {
        val filter = IntentFilter(ACTION_USB_PERMISSION)
        ContextCompat.registerReceiver(
            requireActivity(),
            usbReceiver,
            filter,
            ContextCompat.RECEIVER_EXPORTED
        )
    }

    private fun checkAndRequestAccessory() {
        val accessories = usbManager.accessoryList
        if (!accessories.isNullOrEmpty()) {
            XLog.i("全部 accessory: $accessories")
            printLineToUI("全部 Accessory: ${accessories.map { it.toString() }}")
            val accessory = accessories[0]
            XLog.i("准备请求权限的 accessory: $accessory")
            printLineToUI("准备请求权限的 accessory: $accessory")
            if (usbManager.hasPermission(accessory)) {
                Toaster.show("已拥有权限，直接通信")
                startCommunication(accessory)
            } else {
                requestPermission(accessory)
            }
            XLog.i("等待连接 USB Accessory")
            updateStatus("等待连接...")
            Toaster.show("等待连接 USB Accessory")
            printLineToUI("等待连接 USB Accessory")
        } else {
            XLog.e("未发现 USB Accessory")
            updateStatus("未连接")
            Toaster.show("未发现 USB Accessory")
            printLineToUI("未发现 USB Accessory")
        }
    }

    private fun requestPermission(accessory: UsbAccessory) {
        val intent = PendingIntent.getBroadcast(
            requireActivity(), 0,
            Intent(ACTION_USB_PERMISSION),
            PendingIntent.FLAG_IMMUTABLE
        )
        usbManager.requestPermission(accessory, intent)
    }

    @Suppress("Deprecation")
    private val usbReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            XLog.d("收到广播: ${intent?.action}")
            printLineToUI(intent?.action.toString())
            if (intent?.action == ACTION_USB_PERMISSION) {
                XLog.i("usbReceiver onReceive: ${intent.extras}")
                printLineToUI(intent.extras.toString())
                val accessory = intent.getParcelableExtra<UsbAccessory>(UsbManager.EXTRA_ACCESSORY)
                if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                    accessory?.let { startCommunication(it) }
                } else {
                    XLog.e("USB 权限被拒绝")
                    Toaster.show("USB 权限被拒绝")
                    printLineToUI("USB 权限被拒绝")
                }
            }
        }
    }

    private fun startCommunication(accessory: UsbAccessory) {
        communicator = object : UsbAccessoryCommunicator(requireContext()) {
            override fun onReceive(payload: ByteArray, length: Int) {
                val received = String(payload, 0, length)
                XLog.i("onReceive: $received")
                printLineToUI(getString(com.hjh.res.R.string.local_receive) + received)
            }

            override fun onConnected() {
                XLog.i("onConnected")
                updateStatus("已连接")
                Toaster.show("已连接")
                printLineToUI("connected")
            }

            override fun onDisconnected() {
                XLog.i("onDisconnected")
                updateStatus("已断开")
                Toaster.show("连接断开")
                printLineToUI("disconnected")
            }

            override fun onError(msg: String) {
                XLog.e("onError: $msg")
                updateStatus("错误")
                Toaster.show("异常： $msg")
                printLineToUI("error: $msg")
            }
        }.apply {
            openAccessory(accessory)
        }
    }

    private fun sendString(string: String) {
        communicator?.let {
            it.send(string.toByteArray())
            printLineToUI(getString(com.hjh.res.R.string.local_send) + string)
        } ?: run {
            printLineToUI("连接异常，发送失败")
        }
    }

    @SuppressLint("SetTextI18n")
    private fun updateStatus(status: String) {
        lifecycleScope.launch(Dispatchers.Main) {
            binding.statusText.text = getString(com.hjh.res.R.string.connect_status) + status
        }
    }

    @SuppressLint("SetTextI18n")
    private fun printLineToUI(line: String) {
        lifecycleScope.launch(Dispatchers.Main) {
            // 追加新日志到末尾
            binding.contentText.append("$line\n")

            // 滚动到底部
            binding.accessoryScrollView.post {
                binding.accessoryScrollView.fullScroll(View.FOCUS_DOWN)
            }
        }
    }
}